home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fs / fsTopMigrate.c < prev    next >
C/C++ Source or Header  |  1990-11-06  |  14KB  |  457 lines

  1. /*
  2.  * fsTopMigrate.c --
  3.  *
  4.  * Procedures to handle migrating open files between machines.  The basic
  5.  * strategy is to first do some local book-keeping on the client we are
  6.  * leaving, then ship state to the new client, then finally tell the
  7.  * I/O server about it, and finish up with local book-keeping on the
  8.  * new client.  There are three stream-type procedures used: 'migStart'
  9.  * does the initial book-keeping on the original client, 'migEnd' does
  10.  * the final book-keeping on the new client, and 'migrate' is called
  11.  * on the I/O server to shift around state associated with the client.
  12.  *
  13.  * Copyright (C) 1985, 1988, 1989 Regents of the University of California
  14.  * Permission to use, copy, modify, and distribute this
  15.  * software and its documentation for any purpose and without
  16.  * fee is hereby granted, provided that the above copyright
  17.  * notice appear in all copies.  The University of California
  18.  * makes no representations about the suitability of this
  19.  * software for any purpose.  It is provided "as is" without
  20.  * express or implied warranty.
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /sprite/src/kernel/fs/RCS/fsTopMigrate.c,v 9.3 90/11/06 16:51:02 shirriff Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27.  
  28. #include <sprite.h>
  29. #include <fs.h>
  30. #include <fsutil.h>
  31. #include <fsconsist.h>
  32. #include <fspdev.h>
  33. #include <fsio.h>
  34. #include <fsprefix.h>
  35. #include <fsNameOps.h>
  36. #include <fsStat.h>
  37. #include <byte.h>
  38. #include <rpc.h>
  39. #include <procMigrate.h>
  40. #include <string.h>
  41. #include <stdio.h>
  42.  
  43. extern int fsio_MigDebug;
  44. #define DEBUG( format ) \
  45.     if (fsio_MigDebug) { printf format ; }
  46.  
  47.  
  48. /*
  49.  * ----------------------------------------------------------------------------
  50.  *
  51.  * Fs_InitiateMigration --
  52.  *
  53.  *    Return the size of the encapsulated file system state.
  54.  *    (Note: for now, we'll let the encapsulation procedure do the same
  55.  *    work (in part); later things can be simplified to use a structure
  56.  *    and to keep around some info off the ClientData hook.)
  57.  *
  58.  * Results:
  59.  *    SUCCESS is returned directly; the size of the encapsulated state
  60.  *    is returned in infoPtr->size.
  61.  *
  62.  * Side effects:
  63.  *    None.
  64.  *
  65.  * ----------------------------------------------------------------------------
  66.  *
  67.  */
  68.  
  69. /* ARGSUSED */
  70. ReturnStatus
  71. Fs_InitiateMigration(procPtr, hostID, infoPtr)
  72.     Proc_ControlBlock *procPtr;            /* process being migrated */
  73.     int hostID;                    /* host to which it migrates */
  74.     Proc_EncapInfo *infoPtr;            /* area w/ information about
  75.                          * encapsulated state */
  76. {
  77.     Fs_ProcessState *fsPtr;
  78.     int numStreams;
  79.     int streamFlagsLen;
  80.     Fsprefix *prefixPtr;
  81.     int cwdLength;
  82.  
  83.  
  84.     fsPtr = procPtr->fsPtr;
  85.     numStreams = fsPtr->numStreams;
  86.     /*
  87.      * Get the prefix for the current working directory, and its size.
  88.      * We pass the name over so it can be opened to make sure the prefix
  89.      * is available.
  90.      */
  91.     if (fsPtr->cwdPtr->nameInfoPtr == (Fs_NameInfo *)NIL) {
  92.     panic("Fs_GetEncapSize: no name information for cwd.\n");
  93.     return(FAILURE);
  94.     }
  95.     prefixPtr = fsPtr->cwdPtr->nameInfoPtr->prefixPtr;
  96.     if (prefixPtr == (Fsprefix *)NIL) {
  97.     panic("Fs_GetEncapSize: no prefix for cwd.\n");
  98.     return(FAILURE);
  99.     }
  100.     cwdLength = Byte_AlignAddr(prefixPtr->prefixLength + 1);
  101.     
  102.     /*
  103.      * When sending an array of characters, it has to be even-aligned.
  104.      */
  105.     streamFlagsLen = Byte_AlignAddr(numStreams * sizeof(char));
  106.     
  107.     /*
  108.      * Send the groups, file permissions, number of streams, and encapsulated
  109.      * current working directory.  For each open file, send the
  110.      * streamID and encapsulated stream contents.
  111.      *
  112.      *            data            size
  113.      *         ----            ----
  114.      *         # groups        int
  115.      *            groups            (# groups) * int
  116.      *        permissions        int
  117.      *        # files            int
  118.      *        per-file flags        (# files) * char
  119.      *        encapsulated files    (# files) * (Fsio_MigInfo + int)
  120.      *        cwd            Fsio_MigInfo + int + strlen(cwdPrefix) + 1
  121.      */
  122.     infoPtr->size = (4 + fsPtr->numGroupIDs) * sizeof(int) +
  123.         streamFlagsLen + numStreams * (sizeof(Fsio_MigInfo) + sizeof(int)) +
  124.         sizeof(Fsio_MigInfo) + cwdLength;
  125.     return(SUCCESS);    
  126. }
  127.  
  128.  
  129. /*
  130.  * ----------------------------------------------------------------------------
  131.  *
  132.  * Fs_GetEncapSize --
  133.  *
  134.  *    Return the size of the encapsulated stream.
  135.  *
  136.  * Results:
  137.  *    The size of the migration information structure.
  138.  *
  139.  * Side effects:
  140.  *    None.
  141.  *
  142.  * ----------------------------------------------------------------------------
  143.  *
  144.  */
  145.  
  146. int
  147. Fs_GetEncapSize()
  148. {
  149.     return(sizeof(Fsio_MigInfo));
  150. }
  151.  
  152.  
  153. /*
  154.  *----------------------------------------------------------------------
  155.  *
  156.  * Fs_EncapFileState --
  157.  *
  158.  *    Encapsulate the file system state of a process for migration.  
  159.  *
  160.  * Results:
  161.  *    Any error during stream encapsulation
  162.  *    is returned; otherwise, SUCCESS.  The encapsulated state is placed
  163.  *    in the area referenced by ptr.
  164.  *
  165.  * Side effects:
  166.  *    None.  
  167.  *
  168.  *----------------------------------------------------------------------
  169.  */
  170.  
  171. /* ARGSUSED */
  172. ReturnStatus
  173. Fs_EncapFileState(procPtr, hostID, infoPtr, ptr)
  174.     register Proc_ControlBlock     *procPtr;  /* The process being migrated */
  175.     int hostID;                   /* host to which it migrates */
  176.     Proc_EncapInfo *infoPtr;           /* area w/ information about
  177.                         * encapsulated state */
  178.     Address ptr;               /* Pointer to allocated buffer */
  179. {
  180.     Fs_ProcessState *fsPtr;
  181.     int numStreams;
  182.     int numGroups;
  183.     int streamFlagsLen;
  184.     Fs_Stream *streamPtr;
  185.     int i;
  186.     ReturnStatus status;
  187.     Fsprefix *prefixPtr;
  188.     int cwdLength;
  189.     int size;
  190.     int encaps;
  191.  
  192.  
  193.     fsPtr = procPtr->fsPtr;
  194.     numStreams = fsPtr->numStreams;
  195.     /*
  196.      * Get the prefix for the current working directory, and its size.
  197.      * We pass the name over so it can be opened to make sure the prefix
  198.      * is available.
  199.      */
  200.     if (fsPtr->cwdPtr->nameInfoPtr == (Fs_NameInfo *)NIL) {
  201.     panic("Fs_EncapFileState: no name information for cwd.\n");
  202.     return(FAILURE);
  203.     }
  204.     prefixPtr = fsPtr->cwdPtr->nameInfoPtr->prefixPtr;
  205.     if (prefixPtr == (Fsprefix *)NIL) {
  206.     panic("Fs_EncapFileState: no prefix for cwd.\n");
  207.     return(FAILURE);
  208.     }
  209.     cwdLength = Byte_AlignAddr(prefixPtr->prefixLength + 1);
  210.     
  211.     /*
  212.      * When sending an array of characters, it has to be even-aligned.
  213.      */
  214.     streamFlagsLen = Byte_AlignAddr(numStreams * sizeof(char));
  215.     
  216.     /*
  217.      * Send the groups, file permissions, number of streams, and encapsulated
  218.      * current working directory.  For each open file, send the
  219.      * streamID and encapsulated stream contents.
  220.      *
  221.      *            data            size
  222.      *         ----            ----
  223.      *         # groups        int
  224.      *            groups            (# groups) * int
  225.      *        permissions        int
  226.      *        # files            int
  227.      *        per-file flags        (# files) * char
  228.      *        encapsulated files    (# files) * (Fsio_MigInfo + int)
  229.      *        cwd            Fsio_MigInfo + int + strlen(cwdPrefix) + 1
  230.      */
  231.     size = (4 + fsPtr->numGroupIDs) * sizeof(int) +
  232.         streamFlagsLen + numStreams * (sizeof(Fsio_MigInfo) + sizeof(int)) +
  233.         sizeof(Fsio_MigInfo) + cwdLength;
  234.     if (size != infoPtr->size) {
  235.     panic("Fs_EncapState: size of encapsulated state changed.\n");
  236.     return(FAILURE);
  237.     }
  238.  
  239.     /*
  240.      * Send groups, filePermissions, numStreams, the cwd, and each file.
  241.      */
  242.     
  243.     numGroups = fsPtr->numGroupIDs;
  244.     Byte_FillBuffer(ptr, unsigned int, numGroups);
  245.     if (numGroups > 0) {
  246.     bcopy((Address) fsPtr->groupIDs, ptr, numGroups * sizeof(int));
  247.     ptr += numGroups * sizeof(int);
  248.     }
  249.     Byte_FillBuffer(ptr, unsigned int, fsPtr->filePermissions);
  250.     Byte_FillBuffer(ptr, int, numStreams);
  251.     if (numStreams > 0) {
  252.     bcopy((Address) fsPtr->streamFlags, ptr, numStreams * sizeof(char));
  253.     ptr += streamFlagsLen;
  254.     }
  255.     
  256.     Byte_FillBuffer(ptr, int, prefixPtr->prefixLength);
  257.     strncpy(ptr, prefixPtr->prefix, prefixPtr->prefixLength);
  258.     ptr[prefixPtr->prefixLength] = '\0';
  259.     ptr += cwdLength;
  260.  
  261.     status = Fsio_EncapStream(fsPtr->cwdPtr, ptr);
  262.     if (status != SUCCESS) {
  263.     printf(
  264.           "Fs_EncapFileState: Error %x from Fsio_EncapStream on cwd.\n",
  265.           status);
  266.     return(status);
  267.     }
  268.     fsPtr->cwdPtr = (Fs_Stream *) NIL;
  269.     ptr += sizeof(Fsio_MigInfo);
  270.     encaps = 1;
  271.  
  272.     for (i = 0; i < fsPtr->numStreams; i++) {
  273.     streamPtr = fsPtr->streamList[i];
  274.     if (streamPtr != (Fs_Stream *) NIL) {
  275.         Byte_FillBuffer(ptr, int, i);
  276.         status = Fsio_EncapStream(streamPtr, ptr);
  277.         if (status != SUCCESS) {
  278.         printf(
  279.               "Fs_EncapFileState: Error %x from Fsio_EncapStream.\n",
  280.               status);
  281.         return(status);
  282.         }
  283.         fsPtr->streamList[i] = (Fs_Stream *) NIL;
  284.         encaps++;
  285.     } else {
  286.         Byte_FillBuffer(ptr, int, NIL);
  287.         bzero(ptr, sizeof(Fsio_MigInfo));
  288.     }    
  289.     ptr += sizeof(Fsio_MigInfo);
  290.     }
  291.  
  292. #ifndef CLEAN   
  293.     Proc_MigAddToCounter(encaps, &fs_Stats.mig.filesEncapsulated,
  294.              &fs_Stats.mig.encapSquared);
  295. #endif /* CLEAN */    
  296.  
  297.     return(SUCCESS);
  298. }
  299.  
  300.  
  301. /*
  302.  *----------------------------------------------------------------------
  303.  *
  304.  * Fs_DeencapFileState --
  305.  *
  306.  *    Get the file system state of a process from another node.  The
  307.  *    buffer contains group information, permissions, the encapsulated
  308.  *    current working directory, and encapsulated streams.
  309.  *
  310.  * Results:
  311.  *    If Fsio_DeencapStream returns an error, that error is returned.
  312.  *    Otherwise, SUCCESS is returned.  
  313.  *
  314.  * Side effects:
  315.  *    "Local" Fs_Streams are created and allocated to the foreign process.
  316.  *
  317.  *----------------------------------------------------------------------
  318.  */
  319. /*ARGSUSED*/
  320. ReturnStatus
  321. Fs_DeencapFileState(procPtr, infoPtr, buffer)
  322.     register Proc_ControlBlock     *procPtr; /* The process being migrated */
  323.     Proc_EncapInfo *infoPtr;          /* information about the buffer */
  324.     Address buffer;              /* buffer containing data */
  325. {
  326.     register Fs_ProcessState *fsPtr;
  327.     int i;
  328.     int index;
  329.     int numGroups;
  330.     int numStreams;
  331.     ReturnStatus status;
  332.     char *cwdName;
  333.     int cwdLength;
  334.     Fs_Stream *prefixStreamPtr;
  335.  
  336.     /*
  337.      * Set up an fsPtr for the process.  Initialize some fields so that
  338.      * at any point we can bail out on error by calling Fs_CloseState.  Some
  339.      * fields are initialized from the information from the other host.
  340.      */
  341.     procPtr->fsPtr = fsPtr = mnew(Fs_ProcessState);
  342.     fsPtr->cwdPtr = (Fs_Stream *) NIL;
  343.  
  344.     /*
  345.      * Get group and permissions information.
  346.      */
  347.     Byte_EmptyBuffer(buffer, unsigned int, numGroups);
  348.     fsPtr->numGroupIDs = numGroups;
  349.     if (numGroups > 0) {
  350.     fsPtr->groupIDs = (int *)malloc(numGroups * sizeof(int));
  351.     bcopy(buffer, (Address) fsPtr->groupIDs, numGroups * sizeof(int));
  352.     buffer += numGroups * sizeof(int);
  353.     } else {
  354.     fsPtr->groupIDs = (int *)NIL;
  355.     }
  356.     Byte_EmptyBuffer(buffer, unsigned int, fsPtr->filePermissions);
  357.  
  358.     /*
  359.      * Get numStreams, flags, and the encapsulated cwd.  Allocate memory
  360.      * for the streams and flags arrays if non-empty.  The array of
  361.      * streamFlags may be an odd number of bytes, so we skip past the
  362.      * byte of padding if it exists (using the Byte_AlignAddr macro).
  363.      */
  364.  
  365.     Byte_EmptyBuffer(buffer, int, numStreams);
  366.     fsPtr->numStreams = numStreams;
  367.     if (numStreams > 0) {
  368.     fsPtr->streamList = (Fs_Stream **)
  369.         malloc(numStreams * sizeof(Fs_Stream *));
  370.     fsPtr->streamFlags = (char *)malloc(numStreams * sizeof(char));
  371.     bcopy(buffer, (Address) fsPtr->streamFlags, numStreams * sizeof(char));
  372.     buffer += Byte_AlignAddr(numStreams * sizeof(char));
  373.     for (i = 0; i < fsPtr->numStreams; i++) {
  374.         fsPtr->streamList[i] = (Fs_Stream *) NIL;
  375.     }
  376.     } else {
  377.     fsPtr->streamList = (Fs_Stream **)NIL;
  378.     fsPtr->streamFlags = (char *)NIL;
  379.     }
  380.     /*
  381.      * Get the name of the current working directory and make sure it's
  382.      * an installed prefix.
  383.      */
  384.     Byte_EmptyBuffer(buffer, int, cwdLength);
  385.     cwdName = buffer;
  386.     buffer += Byte_AlignAddr(cwdLength + 1);
  387.  
  388.     /*
  389.      * Unlock the process while doing remote operations using it, or else
  390.      * we can deadlock.
  391.      */
  392.     Proc_Unlock(procPtr);
  393.     
  394.     status = Fs_Open(cwdName, FS_READ | FS_FOLLOW, FS_FILE, 0,
  395.              &prefixStreamPtr);
  396.     if (status != SUCCESS) {
  397.     if (fsio_MigDebug) {
  398.         panic("Unable to open prefix '%s' for migrated process.\n",
  399.            cwdName);
  400.     } else if (proc_MigDebugLevel > 1) {
  401.         printf("%s unable to open prefix '%s' for migrated process.\n",
  402.            "Warning: Fs_DeencapFileState:", cwdName);
  403.     }
  404.     goto failure;
  405.     } else {
  406.     (void) Fs_Close(prefixStreamPtr);
  407.     }
  408.  
  409.     status = Fsio_DeencapStream(buffer, &fsPtr->cwdPtr);
  410.     if (status != SUCCESS) {
  411.     if (fsio_MigDebug) {
  412.         panic("GetFileState: Fsio_DeencapStream returned %x for cwd.\n",
  413.           status);
  414.     } else if (proc_MigDebugLevel > 1) {
  415.         printf("%s Fsio_DeencapStream returned %x for cwd.\n",
  416.           "Warning: Fs_DeencapFileState:", status);
  417.     }
  418.     fsPtr->cwdPtr = (Fs_Stream *) NIL;
  419.         goto failure;
  420.     }
  421.     buffer += sizeof(Fsio_MigInfo);
  422.  
  423.     
  424.  
  425.     /*
  426.      * Get the other streams.
  427.      */
  428.     for (i = 0; i < fsPtr->numStreams; i++) {
  429.     Byte_EmptyBuffer(buffer, int, index);
  430.     if ((status == SUCCESS) && (index != NIL)) {
  431.         status = Fsio_DeencapStream(buffer, &fsPtr->streamList[index]);
  432.         if (status != SUCCESS) {
  433.             printf(
  434.       "Fs_DeencapFileState: Fsio_DeencapStream for file id %d returned %x.\n",
  435.                   index, status);
  436.             fsPtr->streamList[index] = (Fs_Stream *) NIL;
  437.             goto failure;
  438.         }
  439.     }
  440.     buffer += sizeof(Fsio_MigInfo);
  441.     }
  442.  
  443. #ifndef CLEAN   
  444.     Proc_MigAddToCounter(numStreams + 1, &fs_Stats.mig.filesDeencapsulated,
  445.              &fs_Stats.mig.deencapSquared);
  446. #endif /* CLEAN */    
  447.     
  448.     Proc_Lock(procPtr);
  449.     return(SUCCESS);
  450.     
  451. failure:
  452.     Proc_Lock(procPtr);
  453.     Fs_CloseState(procPtr,1);
  454.     return(status);
  455.     
  456. }
  457.